<template>
  <el-form ref="formRef" :model="formData" :rules="rules" v-bind="schema.layout">
    <!-- <el-row :gutter="schema.layout.gutter"> -->
    <template v-for="field in visibleFields" :key="field.field">
      <!-- <el-col :span="getColSpan(field)"> -->
      <el-form-item :label="field.label" :prop="field.field">
        <component
          :is="getFieldComponent(field.type)"
          v-model="formData[field.field]"
          v-bind="field.props"
          :disabled="isFieldDisabled(field)"
          :placeholder="field.placeholder"
        >
          <template v-if="hasOptions(field)">
            <component
              :is="getOptionComponent(field.type)"
              v-for="option in field.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
              :disabled="option.disabled"
            >
            </component>
          </template>
        </component>
      </el-form-item>
      <!-- </el-col> -->
    </template>
    <!-- </el-row> -->

    <div class="form-actions">
      <el-button type="primary" @click="handleSubmit">{{ schema.submitText || '提交' }}</el-button>
      <el-button @click="handleReset">{{ schema.resetText || '重置' }}</el-button>
    </div>
  </el-form>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import type { FormInstance } from 'element-plus'
import type { FormSchema, FormField, VisibilityRule } from '@/types/form'
const props = defineProps<{
  schema: FormSchema
  modelValue: Record<string, any>
}>()

const emit = defineEmits(['update:modelValue', 'submit', 'reset'])

const formRef = ref<FormInstance>()
const formData = ref({ ...props.modelValue })

// 计算可见字段
const visibleFields = computed(() => {
  return props.schema.fields.filter((field) => {
    return isFieldVisible(field, formData.value)
  })
})

// 生成验证规则
const rules = computed(() => {
  const result: Record<string, any> = {}
  props.schema.fields.forEach((field) => {
    if (field.rules) {
      result[field.field] = field.rules
    }
  })
  return result
})

// 获取字段组件
const getFieldComponent = (type: string) => {
  const componentMap: Record<string, string> = {
    input: 'el-input',
    select: 'el-select',
    radio: 'el-radio-group',
    checkbox: 'el-checkbox-group',
    date: 'el-date-picker',
    switch: 'el-switch',
    upload: 'el-upload'
  }
  return componentMap[type]
}

// 获取选项组件
const getOptionComponent = (type: string) => {
  const componentMap: Record<string, string> = {
    select: 'el-option',
    radio: 'el-radio',
    checkbox: 'el-checkbox'
  }
  return componentMap[type]
}

// 判断字段是否有选项
const hasOptions = (field: FormField) => {
  return ['select', 'radio', 'checkbox'].includes(field.type) && field.options
}

// // 计算列宽
// const getColSpan = (field: FormField) => {
//   const defaultCols = props.schema.layout.cols || 24
//   return field.col || Math.floor(24 / defaultCols)
// }

// 判断字段是否禁用
const isFieldDisabled = (field: FormField) => {
  if (typeof field.disabled === 'function') {
    return field.disabled(formData.value)
  }
  return field.disabled
}

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return
  await formRef.value.validate()
  emit('submit', formData.value)
}

// 重置表单
const handleReset = () => {
  if (!formRef.value) return
  formRef.value.resetFields()
  emit('reset')
}

// 监听数据变化
watch(
  () => formData.value,
  (val) => {
    emit('update:modelValue', val)
  },
  { deep: true }
)

// 判断字段是否显示
const isFieldVisible = (field: FormField, values: any): boolean => {
  if (typeof field.show === 'boolean') {
    return field.show
  }

  if (!field.show) {
    return true
  }

  return evaluateVisibilityRule(field.show, values)
}

// 评估显隐规则
const evaluateVisibilityRule = (rule: VisibilityRule, values: any): boolean => {
  if (rule.and) {
    return rule.and.every((r) => evaluateVisibilityRule(r, values))
  }

  if (rule.or) {
    return rule.or.some((r) => evaluateVisibilityRule(r, values))
  }

  const fieldValue = values[rule.field]

  const operatorMap = {
    '=': (fieldValue: any, ruleValue: any) => fieldValue === ruleValue,
    '!=': (fieldValue: any, ruleValue: any) => fieldValue !== ruleValue,
    '>': (fieldValue: any, ruleValue: any) => fieldValue > ruleValue,
    '<': (fieldValue: any, ruleValue: any) => fieldValue < ruleValue,
    '>=': (fieldValue: any, ruleValue: any) => fieldValue >= ruleValue,
    '<=': (fieldValue: any, ruleValue: any) => fieldValue <= ruleValue,
    includes: (fieldValue: any, ruleValue: any) =>
      Array.isArray(fieldValue) && fieldValue.includes(ruleValue),
    empty: (fieldValue: any) =>
      !fieldValue || (Array.isArray(fieldValue) && fieldValue.length === 0),
    notEmpty: (fieldValue: any) =>
      fieldValue && (!Array.isArray(fieldValue) || fieldValue.length > 0)
  }

  return operatorMap[rule.operator]?.(fieldValue, rule.value) ?? true
}
</script>

<style scoped>
.form-actions {
  margin-top: 24px;
  text-align: right;
}
</style>
